package com.ruoyi.app.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.app.annotation.AppSecurity;
import com.ruoyi.app.domain.DictData;
import com.ruoyi.app.service.AppListService;
import com.ruoyi.app.service.AppService;
import com.ruoyi.app.service.ContactService;
import com.ruoyi.app.util.ReqMsg;
import com.ruoyi.app.util.RspMsg;
import com.ruoyi.bizsys.domain.AppDeviceInfo;
import com.ruoyi.bizsys.domain.BankCode;
import com.ruoyi.bizsys.domain.CustAndonLog;
import com.ruoyi.bizsys.domain.FaqQuestion;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.business.domain.GetMultipleDictReq;
import com.ruoyi.business.service.IBankListService;
import com.ruoyi.business.service.ICreditService;
import com.ruoyi.business.service.ICustomerAndonService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.Func;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.extdata.common.config.MonnifyConfig;
import com.ruoyi.extdata.service.IExternalApiService;
import com.ruoyi.system.service.ISysDictDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * swagger app前端公开接口
 *
 * @author ruoyi
 */
@Api("app前端接口")
@RestController
@Slf4j
@RequestMapping("/app/public")
public class AppPublicController extends BaseController {

    @Autowired
    private AppService appService;

    @Autowired
    IFaqQuestionService faqQuestionService;

    @Autowired
    ISysDictDataService sysDictDataService;

    @Autowired
    RedisCache redisCache;

    @Autowired
    MonnifyConfig monnifyConfig;

    @Autowired
    IBankListService iBankListService;

    @Autowired
    IAppDeviceInfoService appDeviceInfoService;

    @Autowired
    IExternalApiService externalApiService;

    @Autowired
    IRuleInService iRuleInService;

    @Autowired
    ICreditService creditService;

    @Autowired
    ICustAndonLogService iCustAndonLogService;

    @Autowired
    ICustomerAndonService iCustomerAndonService;

    @Autowired
    private IAppDeviceContactapplistRelativeService appDeviceContactapplistRelativeService;

    @Autowired
    private AppListService appListService;

    @Autowired
    private ContactService contactService;

    @Autowired
    private IAppsflyerChannelService appsflyerChannelService;


    @AppSecurity
    @ApiOperation("获取首页信息")
    @Log(title = "获取首页信息", businessType = BusinessType.GET)
    @PostMapping("/home")
    public RspMsg homeInfo(@Validated @RequestBody ReqMsg reqMsg) {
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }

        JSONObject dataRsp = appService.getHome(dataJson);
        return RspMsg.RspMsgOk(dataRsp);
    }

    @AppSecurity
    @ApiOperation("登录用户")
    @Log(title = "登录用户", businessType = BusinessType.SUBMIT)
    @PostMapping("/login")
    public RspMsg login(@Validated @RequestBody ReqMsg reqMsg) {
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }

        //请求参数校验
        if (null == dataJson.get("phone") || StringUtils.isBlank(dataJson.get("phone").toString())
                || null == dataJson.get("countryCode") || StringUtils.isBlank(dataJson.get("countryCode").toString())
                || null == dataJson.get("password") || StringUtils.isBlank(dataJson.get("password").toString())
        ) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }

        JSONObject dataRsp = appService.login(dataJson);
        return RspMsg.RspMsgOk(dataRsp);
    }

    @AppSecurity
    @ApiOperation("注册用户")
    @Log(title = "注册用户", businessType = BusinessType.SUBMIT)
    @PostMapping("/register")
    public RspMsg register(@Validated @RequestBody ReqMsg reqMsg) {
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }

        //请求参数校验
        if (null == dataJson.get("countryCode") || StringUtils.isBlank(dataJson.get("countryCode").toString())
                || null == dataJson.get("phone") || StringUtils.isBlank(dataJson.get("phone").toString())
                || null == dataJson.get("smsType") || StringUtils.isBlank(dataJson.get("smsType").toString())
                || null == dataJson.get("verificationCode") || StringUtils.isBlank(dataJson.get("verificationCode").toString())
        ) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }

        JSONObject dataRsp = appService.register(dataJson);
        return RspMsg.RspMsgOk(dataRsp);
    }

    @AppSecurity
    @ApiOperation("smsLogin")
    @Log(title = "smsLogin", businessType = BusinessType.SUBMIT)
    @PostMapping("/smsLogin")
    public RspMsg smsLogin(@Validated @RequestBody ReqMsg reqMsg) {
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }

        //请求参数校验
        if (null == dataJson.get("countryCode") || StringUtils.isBlank(dataJson.get("countryCode").toString())
                || null == dataJson.get("phone") || StringUtils.isBlank(dataJson.get("phone").toString())
//                || null == dataJson.get("uuid") || StringUtils.isBlank(dataJson.get("uuid").toString())
                || null == dataJson.get("smsType") || StringUtils.isBlank(dataJson.get("smsType").toString())
                || null == dataJson.get("verificationCode") || StringUtils.isBlank(dataJson.get("verificationCode").toString())
        ) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }

        JSONObject dataRsp = appService.smsLogin(dataJson);
        return RspMsg.RspMsgOk(dataRsp);
    }


    @AppSecurity
    @ApiOperation("校验bvn是否存在")
    @Log(title = "BVN校验", businessType = BusinessType.GET)
    @PostMapping("/check/bvn")
    public RspMsg checkBVN(@RequestBody ReqMsg reqMsg) {
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }
        if (Func.isEmpty(dataJson.get("bvn"))) {
            throw new BusinessException(RspEnmu.ILLEGAL_ARGUMENT);
        }
        return RspMsg.RspMsgOk(appService.bvnIsExist(dataJson.getString("bvn")));
    }

    @AppSecurity
    @ApiOperation("校验手机号码是否存在")
    @Log(title = "校验手机号码是否存在", businessType = BusinessType.GET)
    @PostMapping("/check/account")
    public RspMsg checkBAccount(@RequestBody ReqMsg reqMsg) {
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }
        if (Func.isEmpty(dataJson.get("account"))) {
            throw new BusinessException(RspEnmu.ILLEGAL_ARGUMENT);
        }
        return RspMsg.RspMsgOk(appService.accountIsExist(dataJson.getString("account"), dataJson.getString("recommendCode"), dataJson.getString("linkRecommendCode")));
    }

    @AppSecurity
    @ApiOperation("获取首页产品列表")
    @Log(title = "获取首页产品列表", businessType = BusinessType.GET)
    @PostMapping("/productList")
    public RspMsg productList(@Validated @RequestBody ReqMsg reqMsg) {
        return RspMsg.RspMsgOk(appService.getProductList());
    }

    @AppSecurity
    @ApiOperation("获取用户首页信息")
    @Log(title = "获取用户首页信息", businessType = BusinessType.GET)
    @PostMapping("/userHome")
    public RspMsg userHome(@Validated @RequestBody ReqMsg reqMsg) {
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }

        JSONObject dataRsp = appService.getUserHome(dataJson);
        return RspMsg.RspMsgOk(dataRsp);
    }

//    @AppSecurity
//    @ApiOperation("账号删除")
//    @Log(title = "账号删除",businessType = BusinessType.DELETE)
//    @PostMapping("/delete")
//    public RspMsg delete(@Validated @RequestBody ReqMsg reqMsg){
//        //参数转换
//        JSONObject dataJson;
//        if (null == reqMsg.getData() && StringUtils.isBlank(reqMsg.getData().toString())) {
//            throw new BusinessException(RspEnmu.REASON_NOTNULL);
//        }
//        dataJson = JSONObject.parseObject(reqMsg.getData().toString());
//        appService.deleteAccount(getCustNo(),dataJson.toString());
//        return RspMsg.RspMsgOk();
//    }

    @AppSecurity
    @ApiOperation("常见问题")
    @Log(title = "常见问题", businessType = BusinessType.GET)
    @PostMapping("/faq/{type}")
    public RspMsg commonFaq(@RequestBody ReqMsg reqMsg, @PathVariable String type) {

        FaqQuestion faqQuestion = new FaqQuestion();
        faqQuestion.setTagName(type);

        List<FaqQuestion> faqQuestionList = faqQuestionService.selectFaqQuestionList(faqQuestion);

        return RspMsg.RspMsgOk(faqQuestionList);
    }

    @AppSecurity
    @ApiOperation("数据字典")
    @Log(title = "数据字典", businessType = BusinessType.GET)
    @PostMapping("/dict/{type}")
    public RspMsg commonDict(@RequestBody ReqMsg reqMsg, @PathVariable String type) {
        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(type);
        sysDictData.setStatus("0");
        List<SysDictData> sysDictDataList = sysDictDataService.selectDictDataList(sysDictData);
        List<DictData> dictDataList = new ArrayList<>();
        sysDictDataList.stream().forEach(p -> dictDataList.add(DictData.builder().label(p.getDictLabel()).value(p.getDictValue()).sort(p.getDictSort()).build()));
        JSONObject result = new JSONObject();
        result.put("dicData", dictDataList);
        return RspMsg.RspMsgOk(result);
    }

    @AppSecurity
    @ApiOperation("数据字典")
    @Log(title = "数据字典", businessType = BusinessType.GET)
    @PostMapping("/dict/{dictType}/{dictValue}")
    public RspMsg commonDict(@RequestBody ReqMsg reqMsg, @PathVariable(value = "dictType") String dictType, @PathVariable(value = "dictValue") String dictValue) {

        log.debug("数据字典查询，dictType = {}，dictValue = {}", dictType, dictValue);

        SysDictData sysDictData = new SysDictData();
        sysDictData.setDictType(dictType);
        sysDictData.setDictValue(dictValue);
        sysDictData.setStatus("0");
        List<SysDictData> sysDictDataList = sysDictDataService.selectDictDataList(sysDictData);
        DictData dictData = DictData.builder().label(sysDictDataList.get(0).getDictLabel()).value(sysDictDataList.get(0).getDictValue()).build();
        return RspMsg.RspMsgOk(dictData);
    }

    @AppSecurity
    @ApiOperation("App用户退出")
    @Log(title = "App用户退出", businessType = BusinessType.FORCE)
    @PostMapping("/loginOut")
    public RspMsg loginOut(@Validated @RequestBody ReqMsg reqMsg) {
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }

        //请求参数校验
//        if (null == dataJson.get("userId") || StringUtils.isBlank(dataJson.get("userId").toString())) {
//            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
//        }

        appService.loginOut(dataJson);

        return RspMsg.RspMsgOk();
    }

    @AppSecurity
    @ApiOperation("获取唯一流水号")
    @Log(title = "获取唯一流水号", businessType = BusinessType.GET)
    @PostMapping("/serial_no")
    public RspMsg getSerialNo(@Validated @RequestBody ReqMsg reqMsg) {

        JSONObject rst = new JSONObject();
        rst.put("serialNo", IdUtils.reqId());

        return RspMsg.ok(rst);
    }

    @AppSecurity
    @ApiOperation("获取monnify银行数据")
    @Log(title = "获取monnify银行数据", businessType = BusinessType.GET)
    @PostMapping("/getMonnifyBank")
    public RspMsg getMonnifyBank(@RequestBody ReqMsg reqMsg) {
        List<BankCode> bankList = iBankListService.getBankListSorted();
        List<Map> list = new ArrayList<>();
        bankList.forEach(e -> {
            if (!Func.hasEmpty(e.getMonnifyBankCode(), e.getMonnifyBankName())) {
                Map<String, String> map = new HashMap<>();
                map.put("bankName", e.getMonnifyBankName());
                map.put("bankCode", e.getMonnifyBankCode());
                list.add(map);
            }
        });
        return RspMsg.ok(list);
    }

    @AppSecurity
    @ApiOperation("批量获取字段数据")
    @Log(title = "批量获取字段数据", businessType = BusinessType.GET)
    @PostMapping("/getMultipleDict")
    public RspMsg getMultipleDict(@RequestBody ReqMsg reqMsg) {


        //Gson gson = new Gson();
        GetMultipleDictReq getMultipleDictReq = JSON.parseObject(reqMsg.getData().toString(), GetMultipleDictReq.class);
        log.info("请求data：{}", JSON.toJSONString(getMultipleDictReq));
        checkAttribute(getMultipleDictReq);

        Map<String, List<DictData>> map = new HashMap<>();

        for (int i = 0; i < getMultipleDictReq.getKeys().length; i++) {
            String key = getMultipleDictReq.getKeys()[i];
            SysDictData sysDictData = new SysDictData();
            sysDictData.setDictType(key);
            sysDictData.setStatus("0");
            List<SysDictData> sysDictDataList = sysDictDataService.selectDictDataList(sysDictData);
            List<DictData> dictDataList = new ArrayList<>();
            sysDictDataList.stream().forEach(p -> dictDataList.add(DictData.builder().label(p.getDictLabel()).value(p.getDictValue()).sort(p.getDictSort()).build()));
            map.put(key, dictDataList);
        }

        return RspMsg.ok(map);
    }


    @ApiOperation("checkGps")
    @Log(title = "checkGps", businessType = BusinessType.GET)
    @PostMapping("/checkGps")
    public RspMsg testAAA(@RequestBody ReqMsg reqMsg) {

        AppDeviceInfo appDeviceInfoSelect = new AppDeviceInfo();
        appDeviceInfoSelect.setCountryState("Federal Capital Territory");
        appDeviceInfoSelect.setCountry("Nigeria");
        appDeviceInfoSelect.setCity("Abuja Municipal Area Council");
        appDeviceInfoSelect.setAddress("3 Funmilayo Ransome Kuti Rd, Garki, Abuja, Nigeria");
        List<AppDeviceInfo> appDeviceInfos = appDeviceInfoService.selectAppDeviceInfoList(appDeviceInfoSelect);

        for (int i = 0; i < appDeviceInfos.size(); i++) {
            AppDeviceInfo appDeviceInfo = appDeviceInfos.get(i);
            if (StringUtils.isNotBlank(appDeviceInfo.getLatitude()) && StringUtils.isNotBlank(appDeviceInfo.getLongitude())) {
                JSONObject obj = externalApiService.getGeocode(appDeviceInfo.getLatitude(), appDeviceInfo.getLongitude());
                if (null != obj) {
                    if (null != obj.get("address")) {
                        appDeviceInfo.setAddress(obj.getString("address"));
                    }
                    if (null != obj.get("country")) {
                        appDeviceInfo.setCountry(obj.getString("country"));
                    }
                    if (null != obj.get("countryState")) {
                        appDeviceInfo.setCountryState(obj.getString("countryState"));
                    }
                    if (null != obj.get("city")) {
                        appDeviceInfo.setCity(obj.getString("city"));
                    }
                    if (null != obj.get("region")) {
                        appDeviceInfo.setRegion(obj.getString("region"));
                    }
                }

                appDeviceInfoService.updateAppDeviceInfo(appDeviceInfo);

//                if(StringUtils.isNotBlank(appDeviceInfo.getActionKey())){
//                    RuleIn ruleIn = new RuleIn();
//                    ruleIn.setApplySerialNo(appDeviceInfo.getActionKey());
//                    List<RuleIn> ruleIns = iRuleInService.selectRuleInList(ruleIn);
//                    for (int j = 0;j<ruleIns.size();j++){
//                        RuleIn ruleIn1 = new RuleIn();
//                        ruleIn1.setId(ruleIns.get(j).getId());
//                        ruleIn1.setDeviceCity(appDeviceInfo.getCity());
//                        ruleIn1.setDeviceCountry(appDeviceInfo.getCountry());
//                        ruleIn1.setAddress(appDeviceInfo.getAddress());
//                        ruleIn1.setContinent(appDeviceInfo.getCountryState());
//                        iRuleInService.updateRuleIn(ruleIn1);
//                    }
//
//                }
            }
        }

        return RspMsg.ok();
    }


    /**
     * 授信账户表中所有历史数据初始 化写入到额度变更日志表
     *
     * @return
     */
//    @Log(title = "额度变更日志-历史初始化", businessType = BusinessType.INSERT)
//    @PostMapping("/increasedLimit/init")
//    public RspMsg init(@RequestBody ReqMsg reqMsg) {
//        return RspMsg.ok(creditService.creditLineHistoryInit());
//    }
    @AppSecurity
    @ApiOperation("提交按灯")
    @Log(title = "提交按灯", businessType = BusinessType.GET)
    @PostMapping("/submitAndon")
    public RspMsg submitAndon(@Validated @RequestBody ReqMsg reqMsg) {
        //参数转换
        CustAndonLog custAndonLog = JSON.parseObject(reqMsg.getData().toString(), CustAndonLog.class);

        custAndonLog.setCustNo(getCustNo());

        if (StringUtils.isBlank(custAndonLog.getType())) {
            return RspMsg.fail(RspEnmu.PARAM_CANNOT_NULL);
        }

        iCustomerAndonService.insertAndonLog(custAndonLog);
        return RspMsg.ok();
    }

    @AppSecurity
    @ApiOperation("检查是否需要上传通讯录app")
    @Log(title = "检查是否需要上传通讯录app", businessType = BusinessType.GET)
    @PostMapping("/checkContactAppList")
    public RspMsg checkContactAppList(@Validated @RequestBody ReqMsg reqMsg) {
        //参数转换
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }
        //请求参数校验 dataJson.get("applyNo"),
        if (Func.hasEmpty(dataJson.get("fingerprint"))) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }

        int status = appDeviceContactapplistRelativeService.checkContactAppList(dataJson.getString("fingerprint"), getUserId2());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("status", status);

        return RspMsg.RspMsgOk(jsonObject);
    }

    @AppSecurity
    @ApiOperation("新客户通讯录授权")
    @Log(title = "新客户通讯录授权", businessType = BusinessType.INSERT)
    @PostMapping("/custContacts")
    public RspMsg custContactsV228(@Validated @RequestBody ReqMsg reqMsg) {

        log.info("准备转换参数");
        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }
        log.info("准备校验参数");
        //请求参数校验
        if (Func.hasEmpty(dataJson.get("fingerprint"))) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }
        log.info("准备进入防止重复提交");
        String userId = getUserId2();
        log.info("custContactsV228 userId = {}", userId);

        //防重
        appService.repeatSubmit(dataJson.getString("fingerprint") + "_contacts", userId);
        log.info("准备进入逻辑");
        contactService.custContactsV228(dataJson, userId, getCustNo(), getAppVersion());
        return RspMsg.RspMsgOk();
    }

    @AppSecurity
    @ApiOperation("新客户App信息授权")
    @Log(title = "新客户App信息授权", businessType = BusinessType.INSERT)
    @PostMapping("/custAppInfo")
    public RspMsg custAppInfoV228(@Validated @RequestBody ReqMsg reqMsg) {

        //参数转换
        JSONObject dataJson = new JSONObject();
        if (null != reqMsg.getData() && StringUtils.isNotBlank(reqMsg.getData().toString())) {
            dataJson = JSONObject.parseObject(reqMsg.getData().toString());
        }
        //请求参数校验 dataJson.get("applyNo"),
        if (Func.hasEmpty(dataJson.get("fingerprint"))) {
            throw new BusinessException(RspEnmu.PARAM_CANNOT_NULL);
        }
        String userId = getUserId2();
        log.info("custAppInfoV228 userId = {}", userId);

        //防重
        appService.repeatSubmit(dataJson.getString("fingerprint") + "_applist", userId);
        appListService.appListV228(dataJson, userId, getCustNo(), getAppVersion());
        //操作成功后向标记表更新字段
        return RspMsg.RspMsgOk();
    }

    @AppSecurity
    @ApiOperation("appsflyer渠道数据")
    @Log(title = "appsflyer渠道数据", businessType = BusinessType.INSERT)
    @PostMapping("/appsflyerChannel")
    public RspMsg insertAppsflyerChannel(@Validated @RequestBody ReqMsg reqMsg) {
        JSONObject jsonObject = JSONObject.parseObject(reqMsg.getData().toString());
        JSONObject nameValuePairs = jsonObject.getJSONObject("nameValuePairs");
        log.info("nameValuePairs{}", nameValuePairs);
        appsflyerChannelService.insertChannel(nameValuePairs);
        return RspMsg.RspMsgOk();
    }

    @ApiOperation("app日志文件上传")
    @Log(title = "app日志文件上传", businessType = BusinessType.INSERT)
    @PostMapping("/appLogs")
    public RspMsg uploadAppLogs(MultipartFile[] files,Long type){
        appService.uploadAppLogs(files,type);
        return RspMsg.RspMsgOk();
    }

}